package cn.mw.cmdb.service.impl;

import cn.mw.cmdb.entity.DataSourceInfo;
import cn.mw.cmdb.entity.FinanceReport.FinanceReportDictionaryInfo;
import cn.mw.cmdb.entity.FinanceReport.FinanceReportGroupInfo;
import cn.mw.cmdb.mongoMapper.FinanceReportDictionaryInfoMapper;
import cn.mw.cmdb.mongoMapper.FinanceReportGroupInfoMapper;
import cn.mw.cmdb.service.FinanceReportDictionaryService;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.view.ViewConvertContext;
import cn.mw.cmdb.view.ViewManager;
import cn.mw.components.mongodb.entity.SearchParam;
import cn.mw.components.mongodb.exception.BusinessException;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.log.client.LogClientSimple;
import cn.mw.log.enums.BusinessLogType;
import cn.mw.log.enums.LogLevel;
import cn.mw.microMonitorCommon.api.cmdb.TreeView;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.DateUtils;
import cn.mw.microMonitorCommon.util.IDModelType;
import cn.mw.microMonitorCommon.util.ModuleIDManager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class FinanceReportDictionaryServiceImpl extends BaseSearchService<FinanceReportDictionaryInfo> implements FinanceReportDictionaryService {

    @Autowired
    private FinanceReportDictionaryInfoMapper financeReportDictionaryInfoMapper;

    @Autowired
    private FinanceReportGroupInfoMapper financeReportGroupInfoMapper;

    @Autowired
    private ModuleIDManager moduleIDManager;

    @Autowired
    private ViewManager viewManager;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private LogClientSimple logClientSimple;

    @Override
    public boolean addOrUpdateFinanceReportGroupInfo(FinanceReportGroupInfo financeReportGroupInfo) {
        if (StringUtils.isBlank(financeReportGroupInfo.getId())) {
            // 执行新增
            financeReportGroupInfo.setId(moduleIDManager.getIDStr(IDModelType.Model));
            financeReportGroupInfoMapper.insert(financeReportGroupInfo);
        } else {
            Query query;
            try {
                query = new Query(CriteriaWrapper.where(FinanceReportGroupInfo::getId).is(financeReportGroupInfo.getId()));
                Update update = CMDBTool.genMongoUpdate(financeReportGroupInfo, null, null);
                CMDBTool.updateFirst(financeReportGroupInfoMapper, query, update);
            } catch (Exception e) {
                throw new RuntimeException("update FinanceReportGroup error!", e);
            }
        }
        return true;
    }

    @Override
    public boolean deleteFinanceReportGroupInfo(String groupId) throws Exception {
        Query query = new Query(new Criteria().orOperator(CriteriaWrapper.where(FinanceReportGroupInfo::getId).is(groupId)
                , CriteriaWrapper.where(FinanceReportGroupInfo::getGroupPath).in(groupId)));
        financeReportGroupInfoMapper.remove(query);

        Query dataSourceQuery = new Query(CriteriaWrapper.where(FinanceReportGroupInfo::getGroupPath).in(groupId));
        financeReportGroupInfoMapper.remove(dataSourceQuery);
        return true;
    }

    @Override
    public FinanceReportGroupInfo getGroupInfo(String groupId) throws Exception {
        Query query = new Query(CriteriaWrapper.where(FinanceReportGroupInfo::getId).is(groupId));
        return financeReportGroupInfoMapper.findOne(query);
    }

    @Override
    public Object getGroupTree(Integer channel) throws Exception {
        List<TreeView> groupInfoList = financeReportGroupInfoMapper.find(
                new Query(CriteriaWrapper.where(FinanceReportGroupInfo::getChannelId).is(channel)));
        List<FinanceReportDictionaryInfo> financeReportDictionaryInfoList = financeReportDictionaryInfoMapper.find(
                new Query(CriteriaWrapper.where(FinanceReportDictionaryInfo::getChannelId).is(channel)));
        Map<String, Integer> groupId2CountMap = new HashMap<>();
        for (FinanceReportDictionaryInfo financeReportDictionaryInfo : financeReportDictionaryInfoList) {
            if (CollectionUtils.isNotEmpty(financeReportDictionaryInfo.getGroupPath())) {
                financeReportDictionaryInfo.getGroupPath().forEach(item -> {
                    String groupId = item == null ? "" : item;
                    if (!groupId2CountMap.containsKey(groupId)) {
                        groupId2CountMap.put(groupId, 0);
                    }
                    groupId2CountMap.put(groupId, groupId2CountMap.get(groupId) + 1);
                });
            }
        }
        groupInfoList.forEach(item -> {
            item.setCount(groupId2CountMap.getOrDefault((String) item.getId(), 0));
        });
        ViewConvertContext context = new ViewConvertContext();
        return viewManager.getTreeViewObject(groupInfoList, context);
    }

    @Override
    public Boolean addOrUpdateFinanceReportDictionary(FinanceReportDictionaryInfo financeReportDictionaryInfo) throws Exception {
        Query existQuery = new Query(CriteriaWrapper.where(FinanceReportDictionaryInfo::getChannelId).is(financeReportDictionaryInfo.getChannelId()));
        existQuery.addCriteria(CriteriaWrapper.where(FinanceReportDictionaryInfo::getFieldName).is(financeReportDictionaryInfo.getFieldName()));
        if (StringUtils.isNotBlank(financeReportDictionaryInfo.getId())) {
            existQuery.addCriteria(CriteriaWrapper.where(FinanceReportDictionaryInfo::getId).ne(financeReportDictionaryInfo.getId()));
        }
        // 同一个上报通道 字典名不能重复
        FinanceReportDictionaryInfo existInfo = financeReportDictionaryInfoMapper.findOne(existQuery);
        if (existInfo != null) {
            throw new BusinessException("data-unique-error", new Object[]{financeReportDictionaryInfo.getFieldName()});
        }
        financeReportDictionaryInfo.setLastUpdateDate(DateUtils.now());
        if (StringUtils.isBlank(financeReportDictionaryInfo.getId())) {
            // 执行新增
            financeReportDictionaryInfo.setCreateDate(DateUtils.now());
            financeReportDictionaryInfo.setCreator(SecurityUtils.getUser().getNickName());
            financeReportDictionaryInfo.setId(moduleIDManager.getIDStr(IDModelType.Model));
            financeReportDictionaryInfoMapper.insert(financeReportDictionaryInfo);
            logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                    messageSource.getMessage("log-add-finance-report-dictionary", null, LocaleContextHolder.getLocale()));
        } else {
            financeReportDictionaryInfo.setLastUpdatedBy(SecurityUtils.getUser().getNickName());
            Query query  = new Query(CriteriaWrapper.where(DataSourceInfo::getId).is(financeReportDictionaryInfo.getId()));
            Update update = CMDBTool.genMongoUpdate(financeReportDictionaryInfo, null, null);
            CMDBTool.updateFirst(financeReportDictionaryInfoMapper, query, update);
            logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                    messageSource.getMessage("log-update-finance-report-dictionary",null, LocaleContextHolder.getLocale()));
        }
        return true;
    }

    @Override
    public boolean batchDeleteFinanceReportDictionaryInfo(List<String> ids) throws Exception {
        financeReportDictionaryInfoMapper.remove(new Query(CriteriaWrapper.where(FinanceReportDictionaryInfo::getId).in(ids)));
        logClientSimple.addBusinessLog(LogLevel.INFO.getId(), BusinessLogType.CMDB_MANAGE.getId(),
                messageSource.getMessage("log-delete-finance-report-dictionary",null, LocaleContextHolder.getLocale()));
        return true;
    }

    @Override
    public Object getFinanceReportDictionaryInfoByPage(SearchParam param) throws Exception {
        Criteria criteria = genCriteria(param);
        // 设置引擎类型名称及引擎名称
        List<FinanceReportDictionaryInfo> resultList = CMDBTool.selectPageList(financeReportDictionaryInfoMapper, criteria, param);
        ViewConvertContext context = new ViewConvertContext();
        return viewManager.getListViewObject(resultList, FinanceReportDictionaryInfo.class, param, context);
    }

    @Override
    protected FinanceReportDictionaryInfo genObject() {
        return new FinanceReportDictionaryInfo();
    }
}
